#ifndef TAPI32EX_H
#define TAPI32EX_H

#include <Windows.h>

#define CP_UTF8                   65001       // UTF-8 translation
inline int AtoW( const char *src, WCHAR *dst, int bufsize, int max_len = -1 ) 
{
	return	::MultiByteToWideChar( CP_ACP, 0, src, max_len, dst, bufsize );
}
inline int WtoA( const WCHAR *src, char *dst, int bufsize, int max_len=-1 ) 
{
	return	::WideCharToMultiByte( CP_ACP, 0, src, max_len, dst, bufsize, 0, 0 );
}

WCHAR *AtoW( const char *src, bool noStatic = false );

//////////////////////////////////////////////////////////////////////////
extern BOOL ( WINAPI *pfnCryptAcquireContext )( HCRYPTPROV*, LPCSTR, LPCSTR, DWORD, DWORD );
extern BOOL ( WINAPI *pfnCryptReleaseContext )( HCRYPTPROV, DWORD );
extern BOOL ( WINAPI *pfnCryptRandom )( HCRYPTPROV, DWORD, BYTE* );

extern BOOL ( WINAPI *pfnCryptExportKey )( HCRYPTKEY, HCRYPTKEY, DWORD, DWORD, BYTE*, DWORD* );
extern BOOL ( WINAPI *pfnCryptImportKey )( HCRYPTPROV, CONST BYTE*, DWORD, HCRYPTKEY, DWORD, HCRYPTKEY* );
extern BOOL ( WINAPI *pfnCryptGenKey )( HCRYPTPROV, ALG_ID, DWORD, HCRYPTKEY* );
extern BOOL ( WINAPI *pfnCryptGetUserKey )( HCRYPTPROV, DWORD, HCRYPTKEY* );
extern BOOL ( WINAPI *pfnCryptDestroyKey )( HCRYPTKEY );
extern BOOL ( WINAPI *pfnCryptGetKeyParam )( HCRYPTKEY, DWORD, BYTE*, DWORD*, DWORD );
extern BOOL ( WINAPI *pfnCryptSetKeyParam )( HCRYPTKEY, DWORD, BYTE*, DWORD );
extern BOOL ( WINAPI *pfnCryptEncrypt )( HCRYPTKEY, HCRYPTHASH, BOOL, DWORD, BYTE*, DWORD*, DWORD );
extern BOOL ( WINAPI *pfnCryptDecrypt )( HCRYPTKEY, HCRYPTHASH, BOOL, DWORD, BYTE*, DWORD* );

extern BOOL ( WINAPI *pfnCryptCreateHash )( HCRYPTPROV, ALG_ID, HCRYPTKEY, DWORD, HCRYPTHASH* );
extern BOOL ( WINAPI *pfnCryptDestroyHash )( HCRYPTHASH );
extern BOOL ( WINAPI *pfnCryptHashData )( HCRYPTHASH, BYTE*, DWORD, DWORD );
extern BOOL ( WINAPI *pfnCryptSignHash )( HCRYPTHASH, DWORD, LPCSTR, DWORD, BYTE*, DWORD* );
extern BOOL ( WINAPI *pfnCryptGetHashParam )( HCRYPTHASH, DWORD, BYTE*, DWORD*, DWORD );
extern BOOL ( WINAPI *pfnCryptSetHashParam )( HCRYPTHASH, DWORD, const BYTE*, DWORD );

extern BOOL ( WINAPI *pfnCryptVerifySignature )( HCRYPTHASH, CONST BYTE*, DWORD, HCRYPTKEY, LPCSTR, DWORD );
extern BOOL ( WINAPI *pfnCryptProtectData )( DATA_BLOB* pDataIn, LPCWSTR szDataDescr, DATA_BLOB* pOptonalEntropy,
									 PVOID pReserved, CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct,
									 DWORD dwFlags, DATA_BLOB* pDataOut );
extern BOOL ( WINAPI *pfnCryptUnprotectData )( DATA_BLOB* pDataIn, LPWSTR* ppszDataDescr, DATA_BLOB* pOptionalEntropy,
									   PVOID pReserved, CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct,
									   DWORD dwFlags, DATA_BLOB* pDataOut );
//////////////////////////////////////////////////////////////////////////
#define SHA1_SIZE 20
#define MD5_SIZE  16

u_int MakeHash( const void *data, int size, DWORD iv = 0 );

class TDigest 
{
public:
	enum Type { SHA1, MD5 /*, SHA1_LOCAL */ } type;

	TDigest();
	~TDigest();
	BOOL Init( Type _type = SHA1 );
	BOOL Reset();
	BOOL Update( void *data, int size );
	BOOL GetVal( void *data );
	int  GetDigestSize() { return type == MD5 ? MD5_SIZE : SHA1_SIZE; }
	void GetEmptyVal( void *data );

protected:
	HCRYPTPROV	_hProv;
	HCRYPTHASH	_hHash;
	__int64		_updateSize;
};

BOOL TLibInit_AdvAPI32();
BOOL TLibInit_Crypt32();
BOOL TGenRandom( void* buf, int len );

#endif